﻿/*
 * sysinfo.cpp
 *
 *  Created on: 2018年2月14日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_OS_SYS DM_API_EXPORT

#include <dm/os/sys/sysinfo.hpp>
#include <dm/os/sys/taskloader.hpp>

#include <dm/env/cfg.hpp>
#include <dm/os/log/logger.hpp>

#include <dm/os/scopelock.hpp>

#include <boost/interprocess/managed_shared_memory.hpp>

namespace dm{
namespace os{
namespace sys{

using namespace boost::interprocess;

static const char* logModule = "CSysInfo.sys.os.dm";

CSysInfo::SSysInfo::SSysInfo():taskCount(0),lock(),sysState(TsStoped),
		startTs(),refreshTs(),pid(-1){
}

CSysInfo::CSysInfo(){
	try{
		permissions p;
		p.set_unrestricted();
		static managed_shared_memory memmgr(open_or_create,logModule,1024l*1024,0,p);

		m_info = memmgr.find_or_construct<SSysInfo>(unique_instance)();
		if( m_info ){
			int taskSize = dm::env::CCfg::ins().task_size();
			m_taskInfos = memmgr.find_or_construct< STaskInfo >(unique_instance)[taskSize]();

			memmgr.find_or_construct<CTaskLoader>(unique_instance)(this,taskSize);
		}else{
			log().error(THISMODULE "获取共享内存失败");
		}

	}catch( interprocess_exception& e ){
		log().error(STATICMODULE "内存分配失败%s",e.what());
		exit(EXIT_FAILURE);
	}
}

CSysInfo::CSysInfo( const CSysInfo& info ):m_info(info.m_info),m_taskInfos(info.m_taskInfos){
}

CSysInfo& CSysInfo::ins(){
	static CSysInfo i;
	return i;
}

const CSysInfo::SSysInfo* CSysInfo::sysInfo()const{
	return m_info;
}

void CSysInfo::reset(){
	boost::interprocess::shared_memory_object::remove(logModule);
}

/**
 * 获取系统开始运行时刻
 * @param ts
 * @return
 */
bool CSysInfo::sysStartTs( dm::CTimeStamp& ts ){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		ts = m_info->startTs;
		return true;
	}

	return false;
}

/**
 * 获取系统上次刷新时刻
 * @param ts
 * @return
 */
bool CSysInfo::sysRefreshTs( dm::CTimeStamp& ts ){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		ts = m_info->refreshTs;
		return true;
	}

	return false;
}

bool CSysInfo::sysState( ETaskState& state ){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		state = m_info->sysState;
		return true;
	}

	return false;
}

bool CSysInfo::getSysInfo( dm::CTimeStamp& startTs,dm::CTimeStamp& refreshTs,ETaskState& state ){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		startTs = m_info->startTs;
		refreshTs = m_info->refreshTs;
		state = m_info->sysState;
		return true;
	}

	return false;
}

bool CSysInfo::ifSysRunning(){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		return ifProcess( m_info->pid ) && m_info->sysState==TsRunning;
	}else
		return false;
}

void CSysInfo::sysStop(){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		m_info->sysState = TsExting;
	}
}

int CSysInfo::taskCount()const{
	if( m_info )
		return m_info->taskCount;
	else
		return 0;
}

int CSysInfo::getTaskIndex( const char* program,const char* paras )const{
	if( !m_info || !m_taskInfos ||  !program )
		return -1;

	for( int i=0;i<m_info->taskCount;++i ){
		const STaskInfo* info = m_taskInfos+i;
		if( info->program==program ){
			if( paras && strlen(paras)>0 ){
				if( info->paras==paras )
					return i;
			}else{
				if( info->paras.len()==0 )
					return i;
			}
		}
	}

	log().info(THISMODULE "平台未配置任务 %s %s",program,paras);

	return -1;
}

const STaskInfo* CSysInfo::getTaskInfo( const int& idx )const{
	if( idx>=0 && m_info && idx<m_info->taskCount ){
		return m_taskInfos+idx;
	}

	return NULL;
}

STaskInfo* CSysInfo::getTaskInfo( const int& idx ){
	if( idx>=0 && m_info && idx<m_info->taskCount ){
		return m_taskInfos+idx;
	}

	return NULL;
}

bool CSysInfo::ifTaskExist( const int& idx ){
	if( idx>=0 && m_info && m_info->taskCount>idx && m_taskInfos )
		return m_taskInfos[idx].ifExist();

	return false;
}
/**
 * 任务是否在运行
 * @param idx
 * @param now
 * @return
 */
bool CSysInfo::ifTaskRunning( const int& idx ){
	if( idx>=0 && m_info && m_info->taskCount>idx && m_taskInfos )
		return m_taskInfos[idx].ifRunning();

	return false;
}

void CSysInfo::taskStop( const int& idx ){
	if( idx>=0 && m_info && m_info->taskCount>idx && m_taskInfos )
		m_taskInfos[idx].stop();
}

void CSysInfo::sysInit( const dm::CTimeStamp& now ){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		m_info->sysState = TsRunning;
		m_info->startTs.copy(now);
		m_info->refreshTs.copy(now);
#ifdef WIN32
		m_info->pid = GetCurrentProcessId();
#else
		m_info->pid = getpid();
#endif

		for( int i=0;i<m_info->taskCount;++i ){
			m_taskInfos[i].init();
		}
	}
}

void CSysInfo::sysRun( const dm::CTimeStamp& now ){
	if( m_info ){
		dm::os::CScopeLock slock(m_info->lock);
		m_info->sysState = TsRunning;
		m_info->refreshTs.copy(now);
	}
}

}
}
}


